﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpSvn;
using System.Collections.ObjectModel;
using System.Collections;

namespace GestoreSuperProgetto
{
    public partial class SvnRepoBrowser : Form
    {
        private Hashtable hashIcons;
        private SvnClient _client;
        public SvnRepoBrowser(string startUrl, SvnClient client):this()
        {
            _client = client;
            TreeNode rootTree = repoTreeView.Nodes.Add(startUrl);            
            InitializeRepo(startUrl, rootTree);
            rootTree.Expand();
            comboBox1.Text = startUrl;
        }

        public string UrlSelected
        {
            get { return comboBox1.Text; }
            set { comboBox1.Text = value; }
        }

        public SvnRepoBrowser()
        {
            InitializeComponent();

            hashIcons = RegisteredFileType.GetFileTypeAndIcon();
            //_iconListManager = new IconListManager(smallImageList, largeImageList);

            listView2.SmallImageList = smallImageList;
            listView2.LargeImageList = largeImageList;
        }

        private void InitializeRepo(string startUrl, TreeNode rootNode)        
        {
            SvnUriTarget folderTarget = new SvnUriTarget(startUrl);
            List<SvnListEventArgs> filesFound = getFolderFiles(folderTarget);
            rootNode.Nodes.Clear();
            //rootNode.Tag = folderTarget;

            foreach(var svnitem in filesFound)
            {
                if (svnitem.Uri.OriginalString != startUrl && svnitem.Entry.NodeKind == SvnNodeKind.Directory)
                {
                    var nameNode = svnitem.Uri.OriginalString.Replace(startUrl, "").TrimEnd('/').Replace("%20", " ").Replace("%23", "#");
                    var lastNode = rootNode.Nodes.Add(nameNode,nameNode);
                    lastNode.Tag = svnitem;
                    lastNode.Name = rootNode.Nodes[rootNode.Nodes.Count - 1].Text;
                    lastNode.Nodes.Add("EmptyNode");
                }
                else if (svnitem.Uri.OriginalString == startUrl && 
                         svnitem.Entry.NodeKind == SvnNodeKind.Directory)
                    rootNode.Tag = svnitem;
            }
        }

        // GetFolderFiles
        //   Function that, given a SvnClient and Target to a folder, returns a list of files
        private List<SvnListEventArgs> getFolderFiles(SvnTarget folderTarget)
        {
            List<SvnListEventArgs> filesFound = new List<SvnListEventArgs>();
            Collection<SvnListEventArgs> listResults;

            if (_client.GetList(folderTarget, out listResults))
            {
                filesFound = listResults.ToList();
                return filesFound;
            }
            else
                throw new Exception("Failed to retrieve files via SharpSvn");
        }

        private void cancelBtn_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            Close();
        }

        private void okBtn_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            Close();
        }

        private void repoTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if(e.Node.Nodes.Count==1 &&
                e.Node.Nodes[0].Text == "EmptyNode")
            {
                SvnListEventArgs eventArg = e.Node.Tag as SvnListEventArgs;
                InitializeRepo(eventArg.Uri.OriginalString, e.Node);
            }
        }

        private void repoTreeView_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            listView2.Items.Clear();
            SvnListEventArgs eventArg = e.Node.Tag as SvnListEventArgs;

            comboBox1.Text = eventArg.Uri.OriginalString.Substring(0, eventArg.Uri.OriginalString.Count()-1);

            SvnUriTarget folderTarget = new SvnUriTarget(eventArg.Uri.OriginalString);
            List<SvnListEventArgs> filesFound = getFolderFiles(folderTarget);
            foreach (var file in filesFound)
            {
                if (file.Entry.NodeKind == SvnNodeKind.File)
                {
                    string extension = System.IO.Path.GetExtension(file.Uri.OriginalString);

                    int positionImage = -1;
                    positionImage = smallImageList.Images.IndexOfKey(extension);
                    if (positionImage == -1)
                    {
                        var obj = hashIcons[extension];
                        try
                        {
                            if (obj != null)
                            {
                                var iconSmall = RegisteredFileType.ExtractIconFromFile(obj.ToString());
                                var iconLarge = RegisteredFileType.ExtractIconFromFile(obj.ToString(), true);
                                smallImageList.Images.Add(extension, iconSmall);
                                largeImageList.Images.Add(extension, iconLarge);
                                positionImage = smallImageList.Images.IndexOfKey(extension);
                            }
                        }
                        catch
                        { }
                    }

                    var Item = listView2.Items.Add(file.Name, positionImage);
                    Item.SubItems.Add(file.Entry.FileSize.ToString());
                    Item.SubItems.Add(extension);
                    Item.SubItems.Add(file.Entry.Revision.ToString());
                    Item.SubItems.Add(file.Entry.Time.ToShortDateString());
                }
                else if (file.Entry.NodeKind == SvnNodeKind.Directory)
                {
                    if (eventArg.Uri.OriginalString == file.Uri.OriginalString)
                        continue;

                    int positionImage = -1;
                    positionImage = smallImageList.Images.IndexOfKey("directory");

                    var Item = listView2.Items.Add(file.Name, positionImage);
                    Item.SubItems.Add(file.Entry.FileSize.ToString());
                    Item.SubItems.Add("");
                    Item.SubItems.Add(file.Entry.Revision.ToString());
                    Item.SubItems.Add(file.Entry.Time.ToShortDateString());
                }
            }
        }

        private void createFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                var dlgInput = new InputBox() { TitleText ="Create Folder", PromptText="Inserire il nome della cartella che si vuole creare:" };
                if (dlgInput.ShowDialog() == DialogResult.OK &&
                    dlgInput.ValueText != "")
                {
                    var uri = new Uri(comboBox1.Text+"/" + dlgInput.ValueText);
                    var arg = new SvnCreateDirectoryArgs()
                    {
                        LogMessage = ""
                    };
                    _client.RemoteCreateDirectory(uri, arg);
                    var seletedRow = repoTreeView.SelectedNode;
                    TreeNode rootTree = repoTreeView.Nodes[0];
                    InitializeRepo((rootTree.Tag as SvnListEventArgs).Uri.OriginalString, rootTree);
                    comboBox1.Text = (rootTree.Tag as SvnListEventArgs).Uri.OriginalString;

                    var paths = ((SharpSvn.SvnListEventArgs)(seletedRow.Tag)).BasePath.Split('/');

                    foreach (var path in paths)
                    {
                        if (path == "")
                            continue;
                        rootTree.Expand();
                        rootTree = rootTree.Nodes[path];
                    }
                    repoTreeView.SelectedNode = rootTree;
                    rootTree.Expand();
                    rootTree.EnsureVisible();
                }
            }
            catch (Exception ex)
            { }
        }
    }
}
